<template>
  <div id="mars3dContainer" class="mars3d-container"></div>
  <div class="latAndLng" v-if="position">
    经度：{{ position.lng }} 纬度：{{ position.lat }} 高度：{{ position.alt }}
  </div>
  <button @click="dblClickOff">地图双击显示经纬度开关</button>
  <button @click="drawPolygon">使用画图事件</button>
  <button @click="changeCamera">切换相机视角</button>
  <button @click="changeText">开启定时器改变文字</button>
  <button @click="addTerrain">地形服务开关</button>
  <button @click="addTileLayer">天地图影像注记开关</button>
</template>
<script setup>
import { onMounted, ref, onUnmounted } from 'vue'
import * as turf from '@turf/turf'
import * as mars3d from 'mars3d'
import { CanvasBillboard, testFn } from './CanvasBillboard.js'
import {
  graphicPoint,
  graphicLabel,
  graphicLine,
  graphicPolygon,
  graphicIcon,
  graphicModel
} from './graphic.js'
let map = ref()
const position = ref()
// cesium相关.mars3d中有cesium的API，使用下面的方法进行使用
let Cesium = mars3d.Cesium
// 地图配置项
let mapOptions = {
  // 底图图层配（LayerType）
  basemaps: [
    {
      // new mars3d.layer.TdtLayer(options)
      name: '天地图影像',
      icon: 'img/basemaps/tdt_img.png',
      type: 'tdt',
      layer: 'img_d',
      show: true
    },
    {
      name: '离线地图',
      icon: 'img/basemaps/mapboxSatellite.png',
      type: 'xyz',
      url: '//data.mars3d.cn/tile/googleImg/{z}/{x}/{y}.jpg',
      maximumLevel: 12
    },
    {
      name: '单张图片',
      icon: 'img/basemaps/offline.png',
      type: 'image',
      url: '//data.mars3d.cn/file/img/world/world.jpg'
    }
  ],
  // 场景参数
  scene: {
    // 默认相机视角
    // lng:经度  lat：纬度  alt：高度  heading：偏航角（方向角度）  pitch：俯仰角
    // center: { lat: 31.81226, lng: 117.096703, alt: 4000 }
    center: { lat: 23.38652, lng: 116.498266, alt: 5000 }
    // center: { lat: 31.81226, lng: 117.096703, alt: 4000 }
  },
  control: {
    baseLayerPicker: true, // basemaps底图切换按钮
    // homeButton: true, // 视角复位按钮
    // sceneModePicker: true, // 二三维切换按钮
    // navigationHelpButton: true, // 帮助按钮
    // fullscreenButton: true, // 全屏按钮
    // contextmenu: { hasDefault: true } // 右键菜单
    locationBar: {
      cacheTime: 50,
      template: `<div style="color:#FFD545">经度{lng}</div>
          <div style="color:#FFD545">纬度{lat}</div>
        <div class="marse3dLabel">海拔（高度）{alt}</div> `
    }
  }
}
let graphicLayer

// 为矢量数据面绑定右键菜单
const bindLayerContextMenu = () => {
  graphicLayer.bindContextMenu([
    {
      text: '删除对象',
      icon: 'fa fa-trash-o',
      show: function (e) {
        console.log('右键菜单被点击', e)
        let graphic = e.graphic
        return graphic.type === 'polygon'
      },
      callback: function (e) {
        let graphic = e.graphic
        if (graphic) {
          graphicLayer.removeGraphic(graphic)
        }
      }
    },
    {
      text: '计算面积',
      show: function (e) {
        let graphic = e.graphic
        return graphic.type === 'polygon'
      },
      // children: [
      //   {
      //     text: '删除对象',
      //     icon: 'fa fa-trash-o',
      //     show: function (e) {
      //       console.log('右键菜单被点击', e)
      //       let graphic = e.graphic
      //       return graphic.type === 'polygon'
      //     },
      //     callback: function (e) {
      //       let graphic = e.graphic
      //       if (graphic) {
      //         graphicLayer.removeGraphic(graphic)
      //       }
      //     }
      //   }
      // ],
      callback: function (e) {
        let graphic = e.graphic
        if (graphic) {
          let area = turf.area(graphic.toGeoJSON({ closure: true }))
          console.log(area)
        }
        // 打开绑定的弹窗
        graphicLayer.openPopup(e.graphic)
      }
    },
    {
      text: '线段添加中心点',
      show: function (e) {
        let graphic = e.graphic
        return graphic.type === 'polyline'
      },
      callback: function (e) {
        let graphic = e.graphic
        if (graphic) {
          let centerNum = turf.center(graphic.toGeoJSON())
          console.log(centerNum)
          let point = new mars3d.graphic.PointEntity({
            position: centerNum.geometry.coordinates,
            style: {
              color: '#ff0000',
              pixelSize: 10,
              outline: true,
              outlineColor: '#ffffff',
              outlineWidth: 2
            }
          })
          point.addTo(graphicLayer)
        }
      }
    }
  ])
}
// 为图层绑定Pop弹窗
const bindLayerPopup = () => {
  graphicLayer.bindPopup(function (event) {
    const attr = event.graphic.attr || {}
    attr['类型'] = event.graphic.type
    attr['来源'] = '我是layer上绑定的Popup'
    attr['备注'] = '我支持鼠标交互'
    if (event.graphic.type === 'polygon') {
      attr['面积'] = turf.area(event.graphic.toGeoJSON({ closure: true }))
    }
    return mars3d.Util.getTemplateHtml({ title: '矢量图层', template: 'all', attr })
  })
}

const positionFn = event => {
  // 获取地图经纬度
  let { lat, lng, alt } = event.sourceTarget._controls.locationBar.locationData
  position.value = { lat, lng, alt }
  console.log(position.value)
  console.log(this)
}
// 为地图添加事件map.on(EventType, callback())
const Mapfunction = () => {
  map.value.on(mars3d.EventType.load, function (event) {
    console.log('地图加载完成')
  })
  map.value.on(mars3d.EventType.terrainLoadSuccess, function (event) {
    console.log('地形数据加载完成')
  })
  map.value.on(mars3d.EventType.terrainLoadError, function (event) {
    console.log('地形数据加载失败')
  })
}
onMounted(() => {
  testFn()
  map.value = new mars3d.Map('mars3dContainer', mapOptions)
  // 可以使用map对象进行一些操作，例如：map.basemap='离线地图',更新显示指定的地图地图
  // map.value.basemap = '离线地图'
  // 1.创建矢量数据图层
  graphicLayer = new mars3d.layer.GraphicLayer()
  // 2.将图层添加到map上
  map.value.addLayer(graphicLayer)
  // 3.将矢量数据添加到图层
  graphicPoint(graphicLayer)
  graphicLabel(graphicLayer)
  graphicLine(graphicLayer)
  graphicPolygon(graphicLayer)
  graphicIcon(graphicLayer)
  graphicModel(graphicLayer)
  bindLayerContextMenu()
  bindLayerPopup()
  Mapfunction()
  // map的成员属性hasTerrain的使用
  // map.value.hasTerrain = true

  // 获取地图上的所有图层
  console.log(map.value.getLayers())
})

// 改变相机视角setCameraView(cameraView, options)
let cameraNum = 0
let tilesetLayer
let tilesetOption = {
  pid: 2020,
  type: '3dtiles',
  name: '油田联合站',
  url: '//data.mars3d.cn/3dtiles/max-ytlhz/tileset.json',
  position: { lng: 117.094224, lat: 31.815859, alt: 26.4 },
  rotation: { z: 116.2 },
  maximumScreenSpaceError: 1,
  center: { lat: 32.407076, lng: 117.459703, alt: 3361, heading: 358, pitch: -51 }
  // clampToGround: true
}

function addDemoGraphic1(graphicLayer) {
  const arrData = [
    { name: '油罐一', position: [117.09521, 31.814404, 47.3] },
    { name: '油罐二', position: [117.095206, 31.814878, 47.3] },
    { name: '油罐三', position: [117.094653, 31.814428, 47.3] },
    { name: '发电机', position: [117.093428, 31.816959, 31.8] },
    { name: '指挥室', position: [117.093953, 31.814397, 36] },
    { name: '加热罐', position: [117.09385, 31.815837, 36.9] },
    { name: '冷却室', position: [117.094662, 31.816403, 32.9] }
  ]

  for (let i = 0; i < arrData.length; i++) {
    const item = arrData[i]
    // CanvasBillboard是重定义的方法
    const graphic = new mars3d.graphic.CanvasBillboard({
      position: item.position,
      style: {
        text: 18,
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        scaleByDistance: new Cesium.NearFarScalar(800, 0.4, 1200, 0.2),
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000)
      }
    })
    graphicLayer.addGraphic(graphic)
  }
}
let timer = null

onMounted(() => {
  tilesetLayer = new mars3d.layer.TilesetLayer(tilesetOption)
  map.value.addLayer(tilesetLayer)
  // console.log(Cesium)
  addDemoGraphic1(graphicLayer)
})
onUnmounted(() => {
  clearInterval(timer)
  map.value.destroy()
})
const dblClickOff = () => {
  // 使用off(types, fn, context)时，当type对应的on事件有fn时，有两种解除方法
  // 1、off(types, fn, context)中的fn不传，使用off（types）
  // 2、off(types, fn, context)中的fn传，里面的fn需与on事件中的fn一致，才能解绑成功
  if (map.value.listens('dblClick') == true) {
    map.value.off(mars3d.EventType.dblClick, positionFn)
    position.value = null
    console.log('解除地图双击事件')
  } else {
    map.value.on(mars3d.EventType.dblClick, positionFn)
    console.log('地图双击事件加载')
  }
}
const drawPolygon = () => {
  graphicLayer
    .startDraw({
      type: 'polygon',
      style: {
        color: 'yellow',
        width: 2,
        clampToGround: true,
        opacity: 0.5
      }
    })
    .then(function (graphic) {
      console.log('绘制完成', graphic)
    })
}
const changeCamera = () => {
  if (cameraNum == 0) {
    map.value.centerAt(
      {
        lat: 31.81226,
        lng: 117.096703,
        alt: 231,
        heading: 329,
        pitch: -28
      },
      {
        complete: function (event) {
          cameraNum = 1
          console.log('相机视角改变完成')
        }
      }
    )
  } else {
    map.value.centerAt(
      {
        lat: 23.38652,
        lng: 116.498266,
        alt: 5000
      },
      {
        complete: function () {
          cameraNum = 0
          console.log('相机视角改变完成')
        }
      }
    )
  }
}
const changeText = () => {
  function random(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min)
  }
  function method(graphic) {
    // console.log(graphic)
    if (graphic.type === 'canvasBillboard') {
      graphic.text = random(25, 100)
    }
  }

  timer = setInterval(() => {
    // graphicLayer.eachGraphic(method, context, reverse)
    // 遍历所有矢量数据并将其作为参数传递给回调函数(类似数组foreach)
    graphicLayer.eachGraphic(method)
  }, 10000)
}
const addTerrain = () => {
  if (map.value.hasTerrain == true) {
    map.value.hasTerrain = false
    console.log('关闭地形数据')
  } else {
    map.value.hasTerrain = true
    map.value.terrainProvider = mars3d.LayerUtil.createTerrainProvider({
      url: 'http://data.mars3d.cn/terrain'
    })
    console.log('加载地形数据')
  }
}
const addTileLayer = () => {
  if (map.value.hasLayer(2024) == true) {
    map.value.removeLayer(2024)
    map.value.basemap = '天地图影像'
    console.log('关闭天地图影像注记')
  } else {
    let tileLayer = new mars3d.layer.TdtLayer({
      id: 2024,
      name: '天地图影像注记',
      layer: 'img_z',
      key: mars3d.Token.tiandituArr
    })
    map.value.basemap = null
    map.value.addLayer(tileLayer)
    console.log(map.value.getLayers())
  }
}
</script>
<style scoped lang="scss">
/* % - 以包含块的百分比定义高度/宽度 */
.mars3d-container {
  width: 100%;
  height: calc(100% - 85px);
  :deep .marse3dLabel {
    font-size: 16px;
    color: brown;
  }
}
.latAndLng {
  position: fixed;
  top: 60px;
  z-index: 999;
  width: 100px;
  height: 50px;
  font-size: 20px;
  color: rgb(248, 243, 243);
}
</style>
